#include <algorithm>
#include <array>
#include <string>
#include <vector>

#include <benchmark/benchmark.h>

#include "legacy_mem_pool.hpp"
#include "modern_mem_pool.hpp"

/**
 * @brief 基准测试使用的示例类型，模拟具有一定负载的对象。
 */
struct Payload {
  Payload() = default;

  Payload(int id, std::string tag)
      : id{id} {
    const auto len = std::min(tag.size(), buffer.size());
    std::copy_n(tag.data(), len, buffer.begin());
  }

  int id{0};
  std::array<char, 32> buffer{};
};

// Legacy 版本在设计上要求至少保留一个空闲槽位。
// 为保持对比公平，Modern 版本也使用相同的分配次数。
constexpr std::size_t kPoolCapacity   = 1'024;
constexpr std::size_t kAllocPerRound  = kPoolCapacity - 1;

// 原始内存池基准
static void BM_LegacyMemPool(benchmark::State& state) {
  Legacy::MemPool<Payload> pool{kPoolCapacity};
  std::vector<Payload*> handles;
  handles.reserve(kAllocPerRound);

  for (auto _ : state) {
    for (std::size_t i = 0; i < kAllocPerRound; ++i) {
      handles.push_back(pool.allocate(static_cast<int>(i), "legacy_payload"));
    }
    for (auto* ptr : handles) {
      pool.deallocate(ptr);
    }
    handles.clear();

    state.SetItemsProcessed(static_cast<long long>(state.iterations()) *
                            static_cast<long long>(kAllocPerRound));
  }
}

// 改进内存池基准
static void BM_ModernMemPool(benchmark::State& state) {
  Modern::MemPool<Payload> pool{kPoolCapacity};
  std::vector<Payload*> handles;
  handles.reserve(kAllocPerRound);

  for (auto _ : state) {
    for (std::size_t i = 0; i < kAllocPerRound; ++i) {
      handles.push_back(pool.allocate(static_cast<int>(i), "modern_payload"));
    }
    for (auto* ptr : handles) {
      pool.deallocate(ptr);
    }
    handles.clear();

    state.SetItemsProcessed(static_cast<long long>(state.iterations()) *
                            static_cast<long long>(kAllocPerRound));
  }
}

BENCHMARK(BM_LegacyMemPool);
BENCHMARK(BM_ModernMemPool);

BENCHMARK_MAIN();